#ifndef __MY__SERVICE__
#define __MY__SERVICE__ 
#include"data.hpp"
#include <cerrno>
#include "httplib.h"
extern cloud::DataManager* _data;

namespace cloud{
  class Service{
    private:
     int _server_port;
     std::string _server_ip;
     std::string _download_prefix;
     httplib::Server _server;
    private:
    static void Upload(const httplib::Request &req,httplib::Response &rsp){
       //post /upload 正文不全是数据
      std::cout<<"Upload"<<std::endl;
       auto ret=req.get_file_value("file");
       if(ret.name!="file"){
         rsp.status=400;
         return;
       }
       const auto& file=req.get_file_value("file");
       std::string back_dir=Config::GetInstance()->GetBackDir();
       std::string realpath=back_dir+FileUtil(file.filename).FileName();
       FileUtil fu(realpath);
       fu.SetContent(file.content);
       BackupInfo info;
       info.NewBackupInfo(realpath);
       _data->Insert(info);
       return;

     }
    static std::string TimetoStr(time_t time){
    std::string tmp =std::ctime(&time);
    return tmp;
    }
    static void ListShow(const httplib::Request&req,httplib::Response &rsp){
      std::vector<BackupInfo> arry;
      _data->GetAll(&arry);
      std::stringstream ss;
      ss<<"<html><head><title>Download</title></head>";
      ss<<"<body><h1>Download</h1><table>";
      for(auto a:arry){
        ss<<"<tr>";
        std::string filename=FileUtil(a.real_path).FileName();
        ss<<"<td><a href='"<<a.url<<"'>"<<filename<<"</a></td>";
        ss<<"<td align='right'> "<<TimetoStr(a.mtime)<<"</td>";
        ss<<"<td align='right'>"<<a.fsize/1024<<"k </td>";
        ss<<"</tr>";
      }
      ss<<"</table></body></html>";
      rsp.body=ss.str();
      rsp.set_header("Content-Type","text/html");
      rsp.status=200;
      return;
    }
  static std::string GetETag(const cloud::BackupInfo &info){
      //etg:filename-fsize-mtime
      FileUtil fu(info.real_path);
			std::string etag = fu.FileName();
      etag+="-";
      etag+=std::to_string(info.fsize);
      etag+="-";
      etag+=std::to_string(info.mtime);
      return etag;
    }
    static void Download(const httplib::Request&req,httplib::Response &rsp){
      //1.获取客户端请求的资源路径path req.path 
      //2.根据资源路径获取文件备份信息
      BackupInfo info;
      _data->GetOneByURL(req.path,&info);
      //3.判断文件是否被压缩
      if(info.pack_flag==true){
        FileUtil fu(info.pack_path);
        fu.Uncompress(info.real_path);
      //删除压缩包修改备份信息（因为已经没有压缩包了flag）
        fu.Remove();
        info.pack_flag=false;
        _data->Updata(info);
      }
      bool retrans=false;
      std::string old_etag;
      if(req.has_header("If-Range")){
        old_etag=req.get_header_value("If-Range");
        if(old_etag==GetETag(info)){
          retrans=true;
        }
      }
      //4.读取文件数据，放入rsp.body 
      FileUtil fu(info.real_path);
      if(retrans==false){
      fu.GetContent(&rsp.body);
      //5.设置响应头部字段：Etag,Accept-Ranges:bytes
      rsp.set_header("Accept-Ranges","bytes");
      rsp.set_header("Etag",GetETag(info));
      rsp.set_header("Content-Type","application/octet-stream");
      rsp.status=200;
      }
      else{
        //httplib内部实现了对于区间请求也就是断点续传请求的处理
					//只需要我们用户将文件所有数据读取到rsp.body中，它内部会自动根据请求
					//区间，从body中取出指定区间数据进行响应
					// std::string  range = req.get_header_val("Range"); bytes=start-end
					fu.GetContent(&rsp.body);
					rsp.set_header("Accept-Ranges", "bytes");
					rsp.set_header("ETag", GetETag(info));
					rsp.set_header("Content-Type", "application/octet-stream");
					//rsp.set_header("Content-Range", "bytes start-end/fsize");
					rsp.status = 206;//区间请求响应的是206*****
      }

        
}
    public:
       Service(){
        Config*config=Config::GetInstance();
        _server_port=config->GetServerPort();
        _server_ip=config->GetServerIp();
        _download_prefix=config->GetDownloadPrefix();
    }
      bool RunModule(){
         _server.Post("/upload",Upload);
         _server.Get("/listshow",ListShow);
         _server.Get("/",ListShow);
        //正则表达式 .*  任意字符任意次
         std::string download_url=_download_prefix+"(.*)";
        _server.Get(download_url,Download);
        std::cout<<_server.listen("0.0.0.0",_server_port)<<std::endl;
  return true;
}
     
};
}

#endif 
